/*
 * Copyright 2003-2007 (c) Live Media Pty Ltd. <argot@einet.com.au> 
 *
 * This software is licensed under the Argot Public License 
 * which may be found in the file LICENSE distributed 
 * with this software.
 *
 * More information about this license can be found at
 * http://www.einet.com.au/License
 * 
 * The Developer of this software is Live Media Pty Ltd,
 * PO Box 4591, Melbourne 3001, Australia.  The license is subject 
 * to the law of Victoria, Australia, and subject to exclusive 
 * jurisdiction of the Victorian courts.
 */

package com.colony.remote.rpc;

import java.io.IOException;
import java.util.HashMap;

import com.argot.TypeException;
import com.argot.TypeLibrary;
import com.argot.network.DynamicClientTypeMap;
import com.argot.network.TypeClient;
import com.argot.remote.MetaInterface;
import com.argot.remote.MetaLocation;
import com.argot.remote.MetaObject;
import com.colony.ColonyEnvironment;
import com.colony.ColonyException;
import com.colony.IColonyClient;
import com.colony.IContainer;
import com.colony.IProxyFactory;
import com.colony.remote.RemoteException;
import com.colony.transport.Client;

public class RpcClient
implements IColonyClient
{
	private boolean _isBound;
	private Client _transport;
	private HashMap _factoryMap;

	//private String _hostName;
	private ColonyEnvironment _environment;
	private TypeLibrary _library;
	private TypeClient _typeClient;
	private DynamicClientTypeMap _clientTypeMap;
	private RpcMetaClient _rpcMetaClient;
	
	public RpcClient( Client transport )
	{
		_isBound = false;
		_transport = transport;
		_factoryMap = new HashMap();
	}
	
	public IContainer getHostContainer()
	{
		return _environment.getHostContainer();
	}

	public TypeLibrary getTypeLibrary()
	{
		return _library;
	}

	public Object getFront( MetaLocation location ) 
	throws ColonyException, RemoteException, TypeException
	{
		throw new ColonyException("Function not supported");
	}

	public Object getFront( MetaObject metaObject ) 
	throws ColonyException, RemoteException, TypeException
	{
		Class clss = _library.getClass(metaObject.getType());
		return getFactory(clss).getProxy(metaObject.getLocation());
	}

	public IProxyFactory getFactory( Class clss ) 
	throws TypeException
	{
		IProxyFactory factory = (IProxyFactory) _factoryMap.get(clss);
		if (factory == null )
		{
			MetaInterface metaInterface = (MetaInterface) _library.getStructure(_library.getId(clss));
			factory = new RpcMetaStubFactory( _rpcMetaClient, metaInterface, clss );
			setFactory( clss, factory );
		}
		return factory;
	}

	public void setFactory( Class clss, IProxyFactory factory )
	{
		_factoryMap.put(clss,factory);
	}
	
	public void bind( String hostName, ColonyEnvironment environment ) 
	throws RemoteException, TypeException, IOException
	{
		if ( _isBound ) throw new RemoteException( "Client already bound" );
		_isBound = true;

		_environment = environment;
		_library = _environment.getTypeLibrary();
		
		_typeClient = new TypeClient( _library, _transport );
		_clientTypeMap = new DynamicClientTypeMap( _library, _typeClient );
		_rpcMetaClient = new RpcMetaClient( _typeClient, _clientTypeMap );		
	}

	public boolean isBound()
	{
		return _isBound;
	}

}
